Skip to main content

Mario - CS50x 2023

入门

打开 VS Code

首先,点击你的终端窗口内部,然后单独执行 cd。 你会看到如下所示的提示符。

点击终端窗口内部,然后执行

wget https://cdn.cs50.net/2022/fall/psets/1/mario-less.zip

然后按回车键,就可以在你的 codespace 中下载一个名为 mario-less.zip 的 ZIP 文件了。 务必注意 wget 和后面的 URL 之间的空格,以及任何其他字符!

现在执行

来创建一个名为 mario-less 的文件夹。 你现在不需要这个 ZIP 文件了,所以可以执行

并在提示符后输入“y”,然后按回车键,删除你下载的 ZIP 文件。

现在输入

然后按回车键,进入(或者说打开)该目录。 现在你的提示符应该类似下面这样。

如果一切顺利,你应该执行

并看到一个名为 mario.c 的文件。 执行 code mario.c 应该会打开该文件,你将在其中输入此问题集的代码。 如果不是,请检查一下你的步骤,看看哪里出错了!

世界 1-1

在任天堂的《超级马里奥兄弟》游戏里,第一大关 1-1 的结尾部分,马里奥需要爬上一个右对齐的积木金字塔,就像下图展示的那样。

马里奥跳上右对齐金字塔的截图

让我们用 C 语言,以文本的形式,使用井号 (#) 来代表砖块,重建这个金字塔,就像下面这样。 每个井号都比它的宽度稍高,所以金字塔本身也会比它的宽度更高。

       #
##
###
####
#####
######
#######
########

我们编写的程序会叫做 mario。 我们让用户来决定金字塔的高度,首先提示他们输入一个 1 到 8 之间的正整数(包括 1 和 8)。

如果用户在提示时输入 8,程序可能会这样运行:

$ ./mario
Height: 8
#
##
###
####
#####
######
#######
########

如果用户在提示时输入 4,程序可能会这样运行:

$ ./mario
Height: 4
#
##
###
####

如果用户在提示时输入 2,程序可能会这样运行:

如果用户在提示时输入 1,程序可能会这样运行:

如果用户没有输入 1 到 8 之间的正整数(包括 1 和 8),程序应该不断提示用户重新输入,直到输入正确为止。

$ ./mario
Height: -1
Height: 0
Height: 42
Height: 50
Height: 4
#
##
###
####

如何开始? 让我们一步一步地解决这个问题。

演练

伪代码

首先,执行

确保你位于 codespace 的默认目录。

然后,执行

进入你的 mario-less 目录。

然后,执行

来打开该目录中名为 pseudocode.txt 的文件。 在 pseudocode.txt 中编写一些伪代码来实现这个程序,即使你还不确定如何用代码来实现。伪代码的写法没有定式,用简短的语句描述即可。不妨回顾一下,我们之前是如何用伪代码来描述在电话簿中查找联系人的过程。你的伪代码可能会用到函数、条件语句、布尔表达式、循环和变量等概念。

提示

实现方法不止一种,这里只是一种!

  1. 提示用户输入高度
  2. 如果高度小于 1 或大于 8,或者不是整数,则返回上一步
  3. 从 1 迭代到高度:
    1. 在第 i 次迭代时,打印 i 个 '#' 符号并换行

可以参考这里的伪代码,但请勿直接复制粘贴!

提示输入

无论你的伪代码如何,我们先编写C代码来提示用户输入(并在必要时重复提示)。打开 mario 目录下的 mario.c 文件 (提示:回顾之前的步骤).

现在,修改 mario.c,使其提示用户输入金字塔的高度,并将输入存储在一个变量中。如果用户输入的不是1到8之间的正整数,程序需要重复提示用户输入. 然后,打印该变量的值,以确认你已成功存储用户的输入,如下所示。

$ ./mario
Height: -1
Height: 0
Height: 42
Height: 50
Height: 4
Stored: 4

提示

  • 记得可以使用 make 命令编译程序.
  • 回想一下,你可以使用 printf%i 打印一个 int
  • 回想一下,你可以使用 get_int 从用户那里获取一个整数。
  • 回想一下,get_intcs50.h 中声明。
  • 回想一下,我们在讲座中使用 do while 循环在 mario.c 中提示用户输入一个正整数。

构建反向金字塔

现在,如果你的程序能够正确接收输入,就可以进行下一步了。

如你所见,构建左对齐的金字塔比右对齐的要简单一些.

修改 mario.c 文件,使其不再只是打印用户的输入,而是打印一个对应高度的左对齐金字塔。

提示

  • 请记住,井号(#)也只是一个普通字符,因此可以使用 printf 函数打印。

  • 正如 Scratch 拥有 repeat 积木块一样,C 语言也提供了 for 循环,允许你重复执行代码块多次。也许在每次循环迭代中,你可以打印相应数量的井号?

  • 实际上,你可以“嵌套”循环,即在一个“外部”循环中使用变量(例如 i)进行迭代,并在其“内部”循环中使用另一个变量(例如 j)进行迭代。例如,以下代码展示了如何打印一个高度和宽度均为 n 的正方形。当然,本次练习的目标并非打印正方形!

      for (int i = 0; i < n; i++)
    {
    for (int j = 0; j < n; j++)
    {
    printf("#");
    }
    printf("\n");
    }

用点号右对齐

现在,我们将在井号前添加点号(.,即句点符号)来右对齐金字塔,效果如下所示。

.......#
......##
.....###
....####
...#####
..######
.#######
########

修改 mario.c,使其完全按照上述方式执行!

提示

请注意,每行所需点号的数量与该行井号的数量存在一种“互补”关系。对于高度为 8 的金字塔(如上图),第一行只有一个井号,因此有 7 个点。同时,底行有 8 个井号,因此有 0 个点。通过什么公式(或者说算术),你可以打印出那么多的点?

如何测试你的代码

当输入以下数值时,你的代码是否能按预期运行?

  • -1(或其他负数)?
  • 0
  • 18
  • 9 或其他正数?
  • 字母或单词?
  • 如果未输入任何内容,直接按下回车键,程序是否能正确处理?

移除点号

现在剩下的只是最后的润色!修改 mario.c,使其打印空格而不是那些点号!

如何测试你的代码

执行以下命令以使用 check50 评估代码的正确性。但请务必自己编译并测试它!

check50 cs50/problems/2023/x/mario/less

执行以下命令以使用 style50 评估代码的风格。

提示

空格字符可以通过敲击空格键输入,句点字符则通过敲击句点键输入!请记住,printf 要求您用双引号将它们括起来!

如何提交

在您的终端中,执行以下命令以提交您的工作。

submit50 cs50/problems/2023/x/mario/less